package org.hishenframework.core.data.jdbc.template;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

import javax.sql.DataSource;

import org.projectname.entity.book.Book;

public class JdbcList<E> implements List<E> {
	
	public static void main(String[] args) throws Exception {
		Class.forName("com.mysql.jdbc.Driver");
		Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/hishen?characterEncoding=utf-8&amp;generateSimpleParameterMetadata=true", "root", "power6409");
		JdbcList<Book> list = new JdbcList<>(Book.class, conn, "select * from t_book where publication_date < ? or publication_date is null", new Date());
		for (Book book : list) {
			System.out.println(book.getBookName());
		}
		list.clear();
	}
	
	private Class<?> clazz;
	private Connection connection;
	private String sqlSelect;
	private Object[] values;
	
	private String sqlCount;
	
	private PreparedStatement pstmt;
	private ResultSet rs;
	
	private int size = -1;
		
	public JdbcList(Class<?> clazz, DataSource source,String sqlSelect, Object... values) throws SQLException {
		this(clazz, source.getConnection(), sqlSelect, values);
	}
	
	public JdbcList(Class<?> clazz, Connection connection, String sqlSelect, Object... values) {
		this.clazz = clazz;
		this.connection = connection;
		this.sqlSelect = sqlSelect;
		this.sqlCount = "SELECT COUNT(*) FROM (" + sqlSelect + ") AS t";
		this.values = values;
	}
	
	/**
	 * 获取集合大小
	 */
	@Override
	public int size() {
		if (size != -1) {
			return size;
		}
		try (Statement statement = connection.createStatement();
			ResultSet rs = statement.executeQuery(sqlCount) ) {
			if (rs.next()) {
				size = rs.getInt(0);
			}
			return 0;
		} catch (SQLException e) {
			throw new RuntimeException(e);			
		}
	}

	@Override
	public boolean isEmpty() {
		return this.size() == 0 ? true : false;  
	}

	@Override
	public Iterator<E> iterator() {
		try {
			pstmt = connection.prepareStatement(sqlSelect);
			for (int i = 0; i < values.length; i++) {
				pstmt.setObject(i + 1, values[i]);
			}
			rs = pstmt.executeQuery();
			return new Itr();
		} catch (SQLException e) {
			try {
				pstmt.close();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			throw new RuntimeException(e);
		}
	}
	
	private class Itr implements Iterator<E> {

		@Override
		public boolean hasNext() {
			try {
				return JdbcList.this.rs.next();
			} catch (SQLException e) {
				throw new RuntimeException(e);
			}
		}

		@Override
		public E next() {
			return JpaJdbcUtils.getObject(rs, JdbcList.this.clazz);
		}

		@Override
		public void remove() {
			throw new RuntimeException("Not implements");
		}
		
	}

	@Override
	public void clear() {
		this.close();
	}
	
	/**
	 * 关闭集合
	 */
	public void close() {
		if (rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (pstmt != null) {
			try {
				pstmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		try {
			connection.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	@Override
	public E get(int index) {
		try (Statement statement = connection.createStatement();
			ResultSet rs = statement.executeQuery(sqlSelect) ) {
			for (int i = 0; i < index && rs.next(); i++) {
				if (i == index) {
					//rs.geto
				}
			}
			return null;
		} catch (SQLException e) {
			throw new RuntimeException(e);			
		}
	}
	
	@Override
	public Object[] toArray() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public <T> T[] toArray(T[] a) {
		// TODO Auto-generated method stub
		return null;
	}
	
	@Override
	public List<E> subList(int fromIndex, int toIndex) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean contains(Object o) {
		throw new RuntimeException("Not implements");
	}
	
	@Override
	public boolean add(E e) {
		throw new RuntimeException("Not implements");
	}

	@Override
	public boolean remove(Object o) {
		throw new RuntimeException("Not implements");
	}

	@Override
	public boolean containsAll(Collection<?> c) {
		throw new RuntimeException("Not implements");
	}

	@Override
	public boolean addAll(Collection<? extends E> c) {
		throw new RuntimeException("Not implements");
	}

	@Override
	public boolean addAll(int index, Collection<? extends E> c) {
		throw new RuntimeException("Not implements");
	}

	@Override
	public boolean removeAll(Collection<?> c) {
		throw new RuntimeException("Not implements");
	}

	@Override
	public boolean retainAll(Collection<?> c) {
		throw new RuntimeException("Not implements");
	}

	

	@Override
	public E set(int index, E element) {
		throw new RuntimeException("Not implements");
	}

	@Override
	public void add(int index, E element) {
		throw new RuntimeException("Not implements");
	}

	@Override
	public E remove(int index) {
		throw new RuntimeException("Not implements");
	}

	@Override
	public int indexOf(Object o) {
		throw new RuntimeException("Not implements");
	}

	@Override
	public int lastIndexOf(Object o) {
		throw new RuntimeException("Not implements");
	}

	@Override
	public ListIterator<E> listIterator() {
		throw new RuntimeException("Not implements");
	}

	@Override
	public ListIterator<E> listIterator(int index) {
		throw new RuntimeException("Not implements");
	}

}
